/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2006
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.analysisModel;

import java.util.ArrayList;

import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IPoint3d;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.pointValues.PointValues;
import br.ufmg.dees.insane.util.pointValues.StringPointValues;

/**
*A class representing a PlaneTruss analysis model of a FrameElement.
*
*@author Fonseca, Flavio & Pitangueira, Roque
*@version 1.1
*@since September 2003, modified October 2006
*/
public class SpaceTruss extends FrameElmAnalysis {

	private static final long serialVersionUID = 1L;

	public SpaceTruss() {
	}
	
	public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c) {
		IMatrix b = new IMatrix(1,6);
		b.setElement(0,0, d.getElement(0,0));
		b.setElement(0,3, d.getElement(1,0));
		return b;
	}
	
	public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IMatrix d3, IVector n, IMatrix c) {
		return getInternalVariableOperator(d, d2, n, c);
	}
	
	public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c, IMatrix u) {
		return getInternalVariableOperator(d, d2, n, c);
	}

	public IMatrix getDualInternalVariableOperator(IMatrix e) {
		//Matrix e must be FrameElement.getPropertiesMatrix()
		IMatrix d = new IMatrix(1,1);
		d.setElement(0, 0, e.getElement(1, 0)*e.getElement(7, 0));
		return d;
	}

	public IMatrix getStateVariableOperator(IMatrix n2, IVector n1, IMatrix c) {
		if (n2 == null) {
			n2 = new IMatrix(2,1);
		}
		IMatrix n = new IMatrix(3, 6);
		n.setZero();
		n.setElement(0, 0, n1.getElement(0));
		n.setElement(1, 1, n1.getElement(0));
		n.setElement(2, 2, n1.getElement(0));
		n.setElement(0, 3, n1.getElement(1));
		n.setElement(1, 4, n1.getElement(1));
		n.setElement(2, 5, n1.getElement(1));
		return (n);
	}

	public int getNumberOfInternalVariables() {
		return 1;
	}

	public int getNumberOfDualInternalVariables() {
		return 1;
	}

	public String[] getInternalVariablesLabels() {
		String[] Dlabels = {"Ea"};
        return Dlabels;
	}

	public String[] getDualInternalVariablesLabels() {
		String[] Dlabels = {"Nx"};
        return Dlabels;
	}

	public String getLabel() {
		return "PlaneTruss";
	}

	public IMatrix getTransformationMatrix(IMatrix dl, IMatrix cN) {
		
		//Calculating element length, cx, cy, cz and cxz
		IPoint3d point1 = new IPoint3d(cN.getElement(0,0), cN.getElement(0,1), cN.getElement(0,2));
		IPoint3d point2 = new IPoint3d(cN.getElement(1,0), cN.getElement(1,1), cN.getElement(1,2));
		double l = point1.distance(point2);
		double cx = (cN.getElement(1,0) - cN.getElement(0,0)) / l;
		double cy = (cN.getElement(1,1) - cN.getElement(0,1)) / l;
		double cz = (cN.getElement(1,2) - cN.getElement(0,2)) / l;
		double cxz = java.lang.Math.sqrt(cx * cx + cz * cz);
		
		//"Default" transformation matrix
		IMatrix t = new IMatrix(6,6);
		//Setting the value of the matrix for a non-vertical element
		if (cy!=1 && cy!=-1) {
			t.setElement(0, 0, cx);
			t.setElement(0, 1, cy);
			t.setElement(0, 2, cz);
			t.setElement(1, 0, -cx * cy / cxz);
			t.setElement(1, 1, cxz);
			t.setElement(1, 2, -cy * cz / cxz);
			t.setElement(2, 0, -cz / cxz);
			t.setElement(2, 2, cx / cxz);
			t.setElement(3, 3, cx);
			t.setElement(3, 4, cy);
			t.setElement(3, 5, cz);
			t.setElement(4, 3, -cx * cy / cxz);
			t.setElement(4, 4, cxz);
			t.setElement(4, 5, -cy * cz / cxz);
			t.setElement(5, 3, -cz / cxz);
			t.setElement(5, 5, cx / cxz);
		}
		
		//Setting the value of the matrix for a vertical element
		else {
			t.setElement(0, 1, cy);
			t.setElement(1, 0, -cy);
			t.setElement(2, 2, 1);
			t.setElement(3, 4, cy);
			t.setElement(4, 3, -cy);
			t.setElement(5, 5, 1);
		}
		
		return t;
	}

	public ArrayList getDOFLabels(int n) {
		ArrayList <PointValues> al = new ArrayList<PointValues>();
		PointValues spv = new StringPointValues();
	    spv.addPointValue("Dx");
	    spv.addPointValue("Dy");
	    spv.addPointValue("Dz");
		for(int i=0; i<n; i++) {
			al.add(i,spv);
		}
		return al;
	}

	@Override
	public IMatrix getLocalStiffnessMatrix(double[] properties) {
		IMatrix mat = new IMatrix(6,6);
		mat.setZero();
		
		double l = properties [0];
		double e = properties[1];
		double a = properties[7];
		
		//Setting the value of factor = (A*E/L)
		double factor = a * e / l;
		
		//Setting the value of the matrix
		mat.setElement(0, 0, factor);
		mat.setElement(0, 3, -factor);
		mat.setElement(3, 0, -factor);
		mat.setElement(3, 3, factor);
		
		return(mat);
	}

	@Override
	public IMatrix nodalRotationMatrix(double angle1, double angle2) {
		//A SpaceTruss element do not accept inclined supports (in this program)
		IMatrix mat = new IMatrix(6, 6);
		return (mat);
	}

	public ArrayList getDOFLabels() {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getPMatrix() {
		// TODO Auto-generated method stub
		return null;
	}
	
}